﻿#include "ui/button.h"
#include "texture.h"
#include "font.h"
#include "context.h"
#include "draw.h"

using namespace std;
using namespace anip;

ui::ButtonBase::ButtonBase(
	Container* parent, invec2 pos, invec2 size, const wstring& text):
	WithText(parent, pos, size, text)
{
	registerBindableRedraw(normalColor);
	registerBindableRedraw(selectedColor);
	registerBindableRedraw(pressFactor);
	registerBindableRedraw(hoverFactor);
}

void ui::ButtonBase::processMouseEnter()
{
	postSignal({ ui::Signal::Type::NeedsRedraw });
	Control::processMouseEnter();
}

void ui::ButtonBase::processMouseLeave()
{
	postSignal({ ui::Signal::Type::NeedsRedraw });
	Control::processMouseLeave();
}

void ui::ButtonBase::processMouseButton(MouseButton btn, ButtonAction action)
{
	postSignal({ ui::Signal::Type::NeedsRedraw });
	if (enabled)
	{
		if (action == ButtonAction::Down)
		{
			if (toggleOnClick) _select = !_select;

			if (anip::time() - _lastClick < 0.25)
			{
				if (onDoubleClick) onDoubleClick(*this);
				_lastClick = 0.0;
			}
			else
				_lastClick = anip::time();
		} else if (action == ButtonAction::Up)
			if (onClick) onClick(*this);
	}
	Control::processMouseButton(btn, action);
}

void ui::ButtonBase::setSize(invec2 s)
{
	WithText::setSize(s);
	discardTextTexture();
}

ui::Button::Button(Container* parent,
	invec2 pos, invec2 size, const wstring& text) :
	ButtonBase(parent, pos, size, text)
{}

int ui::Button::getTextWidth()
{
	if (layoutOptions.type == LayoutOptions::Flow)
		return (int)r::Flow_Button_MaxWidth;
	return (int)(_size.x - 0.6f * r::RoundRadius);
}

void ui::Button::paint()
{
	color col = _select ? selectedColor : normalColor;
	if (enabled)
	{
		if (_press)
			col = col.mulWithoutAlpha(pressFactor);
		else if (_hover)
			col = col.mulWithoutAlpha(hoverFactor);
	}
	Draw::roundedRect(_absPos, _size, r::RoundRadius, col);
	if (texture != nullptr)
	{
		vec2 t = _size / texture->size();
		vec2 scaled = texture->size() * min(t.x, t.y);
		Draw::texture(_absPos + _size * 0.5f - scaled * 0.5f, scaled, *texture);
	}

	auto textTex = getTextTexture();
	if (textTex != nullptr)
	{
		vec2 tsize = getTextSize();
		Draw::text(_absPos + _size / 2.0f - tsize / 2.0f, tsize, *textTex, textColor);
	}

	WithText::paint();
}

void ui::Button::flow(Flow& f)
{
	if (layoutOptions.type != layoutOptions.Flow)
	{
		Control::flow(f);
		return;
	}

	if (!layoutOptions.noAutoSize)
	{
		vec2 tsize = getTextSize();
		if (layoutOptions.stretchX > 0)
			tsize = { 
				(f.borderRight - f.currentX) * layoutOptions.stretchX, 
				tsize.y + r::Flow_Text_vMargin * 2 };
		else
			tsize += vec2{ r::Flow_Text_hMargin, r::Flow_Text_vMargin } * 2.0f;

		setSize({
			max(tsize.x, layoutOptions.minSize.x),
			max(tsize.y, layoutOptions.minSize.y) });
	}

	defaultFlowLayout(f);
}

void ui::RoundButton::paint()
{
	color col = _select ? selectedColor : normalColor;
	if (enabled)
	{
		if (_press)
			col = col.mulWithoutAlpha(pressFactor);
		else if (_hover)
			col = col.mulWithoutAlpha(hoverFactor);
	}
	Draw::ellipse(_absPos, _size, col);
	if (texture != nullptr)
	{
		vec2 t = _size / texture->size();
		vec2 scaled = texture->size() * min(t.x, t.y);
		Draw::texture(_absPos + _size * 0.5f - scaled * 0.5f, scaled, *texture);
	}
	auto textTex = getTextTexture();
	if (textTex != nullptr)
	{
		vec2 tsize = getTextSize();
		Draw::text(_absPos + _size / 2.0f - tsize / 2.0f, tsize, *textTex, textColor);
	}

	WithText::paint();
}

ui::RoundButton::RoundButton(Container* parent,
	invec2 pos, invec2 size, const wstring& text) :
	ButtonBase(parent, pos, size, text)
{}